<?php
function __autoload($class)
{
  ZPlus::autoload($class);
}

class ZPlus
{
  static $nsmap = array();
  static $cache = array();
  static $dbprofiler = null;
  static $opts  = null;

  public static function init($base = '.', $env = 'development', $opts = array())
  {
    error_reporting(E_ALL);
    if ("development" == $env) ini_set('display_errors', 1);
    else if ("production" == $env) ini_set('display_errors', 0);
    date_default_timezone_set("Asia/Bangkok");

    if (empty($opts['nogzip']) && @ini_get('zlib.output_compression') == 0 &&
        @ini_get('output_handler') != 'ob_gzhandler' &&
        @version_compare(PHP_VERSION, '4.2.0') == 1)
      ob_start("ob_gzhandler");

    $root = realpath(dirname(__FILE__)."/../..");
    $base = realpath($base);
    $module = !empty($opts['module']) ? "$base/{$opts['module']}" : "$base/application";
    $zend_version = !empty($opts['zend']) ? $opts['zend'] : '1.11.11';

    define("ZPlus_ENV", $env);
    define("ZPlus_DIR", realpath(dirname(__FILE__)));
    define("BASE_DIR", $base);
    define("MODULE_DIR", $module);
    define("MULTIMODULE", empty($opts['multimodule']) ? '0' : '1');
    define("LIB_DIR", $root."/library");
    define("ZEND_DIR", LIB_DIR."/zend/$zend_version/library");
    define("GLOBAL_DIR", MODULE_DIR."/config");
 
    set_include_path(implode(PATH_SEPARATOR, array(
      ZEND_DIR, $module,
      get_include_path(),
    )));
    

    if (MULTIMODULE == 0)
      self::$nsmap['Model'] = 'models';
    else
      self::$nsmap = $opts['multimodule'];
    
    //set error report
    set_error_handler(array("ZPlus","handleErrorToException"),E_ALL);    
    // init log
    if(!empty($opts["log"]))
      self::log()->init();
    
    //init dbprofiler();
    if(!empty($opts["dbprofiler"])) {
      self::$dbprofiler = new Zend_Db_Profiler_Firebug('All DB Queries');
      self::$dbprofiler->setEnabled(true);
    }
    
    //init layout
    if(!empty($opts["layout"]))
      Zend_Layout::startMvc();
      
    self::$opts = $opts;  
  }

  public static function autoload($class)
  {
    $i = strrpos($class, "_");
    $p = substr($class, 0, $i);
    $f = substr($class, $i + 1);
    if (isset(self::$nsmap[$p]))
      $name = self::$nsmap[$p].'/'.$f.'.php';
    else
      $name = str_replace('_', '/', $class).'.php';
    include $name;
  }

  public static function universal($file = 'global.ini')
  {
    $index = "ZPlus_global_$file";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
    // new object
    $obj = new Zend_Config_Ini(GLOBAL_DIR.'/'.$file, ZPlus_ENV);
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }

  public static function config($file = 'config.ini')
  {
    $index = "ZPlus_config_{$file}";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
    // new object
    $obj = new Zend_Config_Ini(MODULE_DIR.'/config/'.$file, ZPlus_ENV);
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }

  public static function db($key)
  {
    $index = "ZPlus_db_{$key}";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
    // new object
    $ini = self::universal('db.ini');
    $obj = Zend_Db::factory($ini->zenddb->$key);
    // config charset
    if("Pdo_Mysql" == $ini->zenddb->$key->adapter)
    {
      $charset =  $ini->zenddb->$key->charset;
      if(!empty($charset)) $obj->getConnection()->exec("SET CHARACTER SET $charset");
    }
    // set db profiler
    if(!empty(self::$dbprofiler))
      $obj->setProfiler(self::$dbprofiler);
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }
  
  public static function cache($group = 'default')
  {
    $index = "ZPlus_cache_{$group}";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
    // new object
    $opts = array();
    if (!empty($group))
      $opts['group'] = $group;
    $obj = new ZPlus_Cache($opts);
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }

  public static function run($module = null)
  {
    // set front
    $front = Zend_Controller_Front::getInstance();
    if (MULTIMODULE == 0)
      $front->setControllerDirectory(MODULE_DIR."/".$front->getModuleControllerDirectoryName());
    else
      $front->addModuleDirectory(MODULE_DIR);
    // set router
    $router = $front->getRouter();
    $route = new Zend_Controller_Router_Route(
      (MULTIMODULE != 0 || $module != null) ? ':controller/:action/*' : ':module/:controller/:action/*',
      array("module" => $module, "controller" => "index", "action" => "index")
    );
    $router->addRoute("default", $route);
    // dispatch
    $front->dispatch();
  }

  public static function getParam($param, $def = null)
  {
    if (!isset($_REQUEST[$param]))
      return $def;
    return $_REQUEST[$param];
  }
  /**
   * @return Zend_Log
   */  
  public static function log()
  {
    $index = "ZPlus_Log";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
     // new object
    $obj = new ZPlus_Log();
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }
  
  /**
   * @return Zend_Log
   */
  public static function fb()
  {
    $index = "ZPlus_Firebug_Log";
    // return cached object if registered
    if (isset(self::$cache[$index]))
      return self::$cache[$index];
     // new object
    if ("production" == ZPlus_ENV) 
      $writer = new Zend_Log_Writer_Null();
    else
      $writer = new Zend_Log_Writer_Firebug();
    $obj = new Zend_Log($writer);
    // register & return
    self::$cache[$index] = $obj;
    return $obj;
  }

  public static function handleErrorToException($errno, $errstr, $errfile, $errline)
  {
    if( 0 == error_reporting()) return true; // not throw if use @error-control operator. 
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
  }
}

class ZPlus_Log
{
  private $_log;

  public function __construct()
  {
	$this->_log = new Zend_Log(new Zend_Log_Writer_Stream($this->_file())); 
  }

  public function init()
  {
    ini_set('error_log',$this->_file());
    ini_set('ignore_repeated_source', true);
    ini_set('log_errors',true);
  }

  public function __call($m,$a)
  {
  	call_user_func_array(array($this->_log,$m),$a);
  }
  
  private function _file()
  {
  	$file = BASE_DIR."/logs/error.log";
  	if(file_exists($file) && filesize($file) > 1048576) {
  		rename($file,BASE_DIR."/logs/error.".date("YmdHis").".log");
  	}
  	return $file;
  }
}
